/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package repol190.kernel;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import repol190.geradoreventos.GeradorEventos;
import repol190.ocorrencia.Ocorrencia;
import repol190.ocorrencia.OcorrenciaInexistenteException;
import repol190.viatura.Viatura;
import repol190.viatura.ViaturaInexistenteException;

/**
 *
 * @author micael
 */
public class Kernel implements Runnable{
    
    private FilaDePrioridade filaDeOcorrencias;
    private GeradorEventos eventos;    
    
    public Kernel(GeradorEventos eventos){
       filaDeOcorrencias = new FilaDePrioridade();
       this.eventos = eventos;
    }
    
    public void preencherFila(){
        Collection<Ocorrencia> ocorrencias = eventos.listarOcorrencias();
        Iterator<Ocorrencia> i = ocorrencias.iterator();
        
        while(i.hasNext()){
            Ocorrencia auxiliar = i.next();
            if(auxiliar.getStatus()==0){
                insere(auxiliar);
            }
        }        
    }
    
    public void insere(Ocorrencia o){
        filaDeOcorrencias.inserir(o);
    }
    
    public void imprimir(){
        filaDeOcorrencias.imprimirFila();
    }
    
    public Vector<Viatura> retornaViaturasOciosas(){
        Collection<Viatura> viaturas = eventos.listarViaturas();
        Vector<Viatura> viaturasOciosas = new Vector<Viatura>();
        Iterator<Viatura> i = viaturas.iterator();
        
        while(i.hasNext()){
            Viatura auxiliar = i.next();
            if(auxiliar.getStatus()==1){
                viaturasOciosas.add(auxiliar);
            }
        }
        
        return viaturasOciosas;
    }
    
    public void resolveOcorrencia() throws ViaturaInexistenteException, OcorrenciaInexistenteException{
        preencherFila();
        Ocorrencia paraResolver =  filaDeOcorrencias.getFila().getFirst();
        Vector<Viatura> viaturasOciosas = retornaViaturasOciosas();
        
        ArrayList<Double> vetorDeDistancia = new ArrayList<Double>();
        ArrayList<Viatura> vetorDeViaturas = new ArrayList<Viatura>();
        
        if(viaturasOciosas.isEmpty()){
            //não existem viaturas ociosas para a emergência
            System.out.println("não existem viaturas ociosas para a emergência");
        }else{
            //calcula todas as distancias da ocorrencia para as viaturas
            Iterator<Viatura> i = viaturasOciosas.iterator();
            while(i.hasNext()){
            Viatura auxiliar = i.next();
            vetorDeDistancia.add(calculaDistancia(paraResolver, auxiliar));
            vetorDeViaturas.add(auxiliar);
        }
            //determina a menor distancia
            double menorDistancia = vetorDeDistancia.get(0);
            int indiceDaMenorDistancia = 0;
            for(int j = 1; j < vetorDeDistancia.size(); j++){
                if(menorDistancia>vetorDeDistancia.get(j)){
                    menorDistancia = vetorDeDistancia.get(j);
                    indiceDaMenorDistancia = j;
                }
            }
            //escolhe a viatura
            Viatura viaturaEscolhida = vetorDeViaturas.get(indiceDaMenorDistancia);
            if(calculaDistancia(paraResolver, viaturaEscolhida)==menorDistancia){
                viaturaEscolhida.setOcorrencia(paraResolver);
                viaturaEscolhida.setStatus(2);
                viaturaEscolhida.setEndereco(paraResolver.getEndereco());
                eventos.atualizarViatura(viaturaEscolhida);
                paraResolver.setStatus(1);
                eventos.atualizarOcorrencia(paraResolver);
                
                int qtdeDePoliciais = viaturaEscolhida.getQtdePoliciais();
                while(paraResolver.getQtdePoliciais()> qtdeDePoliciais){
                    vetorDeDistancia.remove(indiceDaMenorDistancia);
                    vetorDeViaturas.remove(indiceDaMenorDistancia);
                    if(vetorDeViaturas.isEmpty()){
                        System.out.println("não existem MAIS viaturas ociosas para a emergência");
                    }else{
                        //determina a menor distancia
                        menorDistancia = vetorDeDistancia.get(0);
                        indiceDaMenorDistancia = 0;
                        for(int j = 1; j < vetorDeDistancia.size(); j++){
                            if(menorDistancia>vetorDeDistancia.get(j)){
                                menorDistancia = vetorDeDistancia.get(j);
                                indiceDaMenorDistancia = j;
                            }
                        }
                        //escolhe a viatura
                        viaturaEscolhida = vetorDeViaturas.get(indiceDaMenorDistancia);
                        if(calculaDistancia(paraResolver, viaturaEscolhida)==menorDistancia){
                            viaturaEscolhida.setOcorrencia(paraResolver);
                            viaturaEscolhida.setStatus(2);
                            viaturaEscolhida.setEndereco(paraResolver.getEndereco());
                            eventos.atualizarViatura(viaturaEscolhida);
                            qtdeDePoliciais = qtdeDePoliciais + viaturaEscolhida.getQtdePoliciais();
                        }else{
                             System.out.println("A viatura escolhida eh a errada");
                    }
                        
                        
                    }
                }
            }else{
                System.out.println("A viatura escolhida eh a errada");
            }
            
            
        }
        
    }
    
    public double calculaDistancia(Ocorrencia o, Viatura v){
        double distancia = -1;
        double termo;
        int eixoX = o.getEndereco().getPosicao().getX() - v.getEndereco().getPosicao().getX();
        int eixoY = o.getEndereco().getPosicao().getY() - v.getEndereco().getPosicao().getY();
        
        termo = Math.pow(eixoX, 2) + Math.pow(eixoY, 2);
        distancia = Math.sqrt(termo);
        
        return distancia;
    }

    public FilaDePrioridade getFilaDeOcorrencias() {
        return filaDeOcorrencias;
    }

    public GeradorEventos getEventos() {
        return eventos;
    }

    @Override
    public void run() {
        
        try {
            resolveOcorrencia();
        } catch (ViaturaInexistenteException ex) {
            Logger.getLogger(Kernel.class.getName()).log(Level.SEVERE, null, ex);
        } catch (OcorrenciaInexistenteException ex) {
            Logger.getLogger(Kernel.class.getName()).log(Level.SEVERE, null, ex);
        }
       
       
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
}
